package com.sale.system.dubbo;

import cn.dev33.satoken.secure.BCrypt;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.sale.common.core.constant.CacheNames;
import com.sale.common.core.domain.R;
import com.sale.common.core.enums.UserStatus;
import com.sale.common.core.exception.ServiceException;
import com.sale.common.core.exception.user.UserException;
import com.sale.common.core.utils.StreamUtils;
import com.sale.common.core.utils.StringUtils;
import com.sale.common.redis.utils.CacheUtils;
import com.sale.common.redis.utils.RedisUtils;
import com.sale.system.api.RemoteUserService;
import com.sale.system.api.domain.SysAuxiliary;
import com.sale.system.api.domain.SysUser;
import com.sale.system.api.domain.dto.SysCustomDto;
import com.sale.system.api.domain.dto.SysTheDropApiDto;
import com.sale.system.api.model.LoginUser;
import com.sale.system.api.model.RoleDTO;
import com.sale.system.api.model.XcxLoginUser;
import com.sale.system.api.domain.SysRole;
import com.sale.system.domain.*;
import com.sale.system.domain.dto.SysTheDropDto;
import com.sale.system.mapper.SysFieldsMapper;
import com.sale.system.mapper.SysRoleMapper;
import com.sale.system.mapper.SysUserMapper;
import com.sale.system.mapper.SysUserRoleMapper;
import com.sale.system.mapper.*;
import com.sale.system.service.ISysConfigService;
import com.sale.system.service.ISysPermissionService;
import com.sale.system.service.ISysUserService;
import com.sale.system.util.SnowflakeIdGenerator;
import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户服务
 *
 * @author Lion Li
 */
@RequiredArgsConstructor
@Service
@DubboService
public class RemoteUserServiceImpl implements RemoteUserService {

    private final ISysUserService userService;
    private final ISysPermissionService permissionService;
    private final ISysConfigService configService;
    private final SysUserMapper userMapper;

    private final SysUserRoleMapper sysUserRoleMapper;

    private final SysFieldsMapper sysFieldsMapper;

    private final SysRoleMapper sysRoleMapper;

    private final SysAccountsMapper sysAccountsMapper;
    @Resource
    private SysUserAccountsMapper sysUserAccountsMapper;

    @Resource
    private SysRoleMenuMapper sysRoleMenuMapper;

    @Resource
    private SysFunctionalParameterMapper sysFunctionalParameterMapper;

    @Resource
    private SysParameterDescriptionMapper sysParameterDescriptionMapper;

    @Resource
    private SysInventoryAccountingMapper sysInventoryAccountingMapper;

    @Resource
    private SysAccountingDetailMapper sysAccountingDetailMapper;

    @Override
    public LoginUser getUserInfo(String username) throws UserException {
        SysUser sysUser = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
            .select(SysUser::getUserName, SysUser::getStatus, SysUser::getTenantId)
            .eq(SysUser::getUserName, username));
        if (ObjectUtil.isNull(sysUser)) {
            throw new UserException("user.not.exists", username);
        }
        if (UserStatus.DISABLE.getCode().equals(sysUser.getStatus())) {
            throw new UserException("user.blocked", username);
        }
        // 此处可根据登录用户的数据不同 自行创建 loginUser
        LoginUser loginUser = buildLoginUser(userMapper.selectUserByUserName(username));
        loginUser.setTenantId(sysUser.getTenantId().toString());
        return loginUser;
    }

    @Override
    public LoginUser getUserInfoByPhonenumber(String phonenumber) throws UserException {
//        SysUser sysUser = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
//                .select(SysUser::getPhonenumber, SysUser::getStatus)
//                .eq(SysUser::getPhonenumber, phonenumber));
        SysUser sysUser = userMapper.selectUserInfo(phonenumber);

        if (ObjectUtil.isNull(sysUser)) {
            throw new UserException("user.not.exists", phonenumber);
        }
        if (UserStatus.DISABLE.getCode().equals(sysUser.getStatus())) {
            throw new UserException("user.blocked", phonenumber);
        }
        // 此处可根据登录用户的数据不同 自行创建 loginUser
        LoginUser loginUser = buildLoginUser(userMapper.selectUserByPhonenumber(phonenumber));

        SysUser sysUser1 = userMapper.selectUserInfo(phonenumber);
        loginUser.setTenantId(sysUser1.getTenantId().toString());
        return loginUser;
    }

    @Override
    public LoginUser getUserInfoByEmail(String email) throws UserException {
        SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
            .select(SysUser::getPhonenumber, SysUser::getStatus)
            .eq(SysUser::getEmail, email));
        if (ObjectUtil.isNull(user)) {
            throw new UserException("user.not.exists", email);
        }
        if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
            throw new UserException("user.blocked", email);
        }
        // 此处可根据登录用户的数据不同 自行创建 loginUser
        return buildLoginUser(userMapper.selectUserByEmail(email));
    }

    @Override
    public XcxLoginUser getUserInfoByOpenid(String openid) throws UserException {
        // todo 自行实现 userService.selectUserByOpenid(openid);
        SysUser sysUser = new SysUser();
        if (ObjectUtil.isNull(sysUser)) {
            // todo 用户不存在 业务逻辑自行实现
        }
        if (UserStatus.DISABLE.getCode().equals(sysUser.getStatus())) {
            // todo 用户已被停用 业务逻辑自行实现
        }
        // 此处可根据登录用户的数据不同 自行创建 loginUser
        XcxLoginUser loginUser = new XcxLoginUser();
        loginUser.setUserId(sysUser.getUserId());
        loginUser.setUsername(sysUser.getUserName());
        loginUser.setUserType(sysUser.getUserType());
        loginUser.setOpenid(openid);
        return loginUser;
    }

    @Override
    public Boolean registerUserInfo(SysUser sysUser) {
        String username = sysUser.getUserName();
        if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser")))) {
            throw new ServiceException("当前系统没有开启注册功能");
        }
        if (!userService.checkUserNameUnique(sysUser)) {
            throw new UserException("user.register.save.error", username);
        }
        boolean b = userService.registerUser(sysUser);

        return b;
    }

    @Override
    public String selectUserNameById(Long userId) {
        return userService.selectUserNameById(userId);
    }

    /**
     * 根据userName获取用户信息
     *
     * @param userName
     * @return
     */
    @Override
    public R<SysUser> getByUserName(String userName) {
        return R.ok(userService.getByUserName(userName));
    }

    /**
     * 通过手机号查询用户信息
     *
     * @param phoneNumber
     * @return
     */
    @Override
    public boolean getByPhone(String phoneNumber, String password) {
        SysUser sysUser = userMapper.selectUserByPhonenumber(phoneNumber);
        sysUser.setPassword(BCrypt.hashpw(password));
        return userMapper.updateById(sysUser) > 0;
    }

    /**
     * 判断当前手机号是否存在
     *
     * @param phoneNumber
     * @return
     */
    @Override
    public boolean IsPhoneExist(String phoneNumber) {
        SysUser sysUser = userMapper.selectUserByPhonenumber(phoneNumber);
        if (sysUser == null) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * 新增账套信息，绑定角色和菜单
     *
     * @param phoneNumber
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean saveAccount(String accountsName, String accountType, Date accountTime, String phoneNumber) {
        //通过手机号查询用户信息
        SysUser sysUser = userMapper.selectUserByPhonenumber(phoneNumber);

        //生成雪花id
        SnowflakeIdGenerator idGenerator = new SnowflakeIdGenerator(1, 1);
        long id = idGenerator.nextId();

        //新增租户信息
        SysAccounts sysAccounts = new SysAccounts();
        sysAccounts.setAccountsName(accountsName);
        sysAccounts.setAccountsType(accountType);
        sysAccounts.setAccountsTime(accountTime);
        sysAccounts.setAccountsId(id);
        sysAccounts.setTenantId(id);
        sysAccounts.setCreateBy("admin");
        boolean insertAccount = sysAccountsMapper.insert(sysAccounts) > 0;

        if (insertAccount) {
            //查询系统参数表
            List<SysParameterDescription> sysParameterDescriptions = sysParameterDescriptionMapper.selectList();

            List<SysFunctionalParameter> sysFunctionalParameterList = new ArrayList<>();

            List<SysAccountingDetail> accountingDetailList = new ArrayList<>();

            SysInventoryAccounting sysInventoryAccounting = new SysInventoryAccounting();
            sysInventoryAccounting.setAccountsId(id);
            sysInventoryAccounting.setTenantId(id);
            sysInventoryAccounting.setCostAccountingMethod(1);
            sysInventoryAccounting.setCostAccountingWay(1);
            sysInventoryAccountingMapper.insert(sysInventoryAccounting);

            for (SysParameterDescription sysParameterDescription : sysParameterDescriptions) {
                if (sysParameterDescription.getType() == 1) {
                    //新增账套参数表
                    SysFunctionalParameter sysFunctionalParameter = new SysFunctionalParameter();
                    sysFunctionalParameter.setAccountsId(id);
                    sysFunctionalParameter.setOperatingState(1);
                    sysFunctionalParameter.setTenantId(id);
                    sysFunctionalParameter.setDescriptionId(sysParameterDescription.getDescriptionId());
                    sysFunctionalParameterList.add(sysFunctionalParameter);
                } else {
                    SysAccountingDetail sysAccountingDetail = new SysAccountingDetail();
                    sysAccountingDetail.setInventoryAccountingId(sysInventoryAccounting.getInventoryAccountingId());
                    sysAccountingDetail.setAccountingOperate(2);
                    sysAccountingDetail.setTenantId(id);
                    sysAccountingDetail.setDescriptionId(sysParameterDescription.getDescriptionId());
                    accountingDetailList.add(sysAccountingDetail);
                }

            }
            sysAccountingDetailMapper.insertBatch(accountingDetailList);
            //批量新增系统参数
            sysFunctionalParameterMapper.insertBatch(sysFunctionalParameterList);

            //新增用户账套中间表
            SysUserAccounts sysUserAccounts = new SysUserAccounts();
            sysUserAccounts.setAccountsId(id);
            sysUserAccounts.setTenantId(id);
            sysUserAccounts.setUserId(sysUser.getUserId());
            sysUserAccountsMapper.insert(sysUserAccounts);

            SnowflakeIdGenerator idGenerator1 = new SnowflakeIdGenerator(1, 1);
            long roleId = idGenerator1.nextId();

            //新增角色信息
            SysRole sysRole = new SysRole();
            //sysRole.setRoleCode("admin");//角色编码
            sysRole.setRoleName("超级管理员");//角色名称
            sysRole.setStatus("1");//启用状态
          //  sysRole.setReceiptAuthority(1);
            sysRole.setCreateTime(new Date());
            sysRole.setCreateBy("admin");
         //   sysRole.setDeptId(103);
         //   sysRole.setWorkbenchDataType(1);
            sysRole.setRoleId(roleId);
            sysRole.setTenantId(id);
            int insert = sysRoleMapper.insert(sysRole);

            if (insert > 0) {
                //新增角色用户中间表
                SysUserRole sysUserRole = new SysUserRole();
                //给超级管理员权限
                sysUserRole.setRoleId(roleId);
                sysUserRole.setUserId(sysUser.getUserId());
                sysUserRole.setTenantId(id);
                int insert1 = sysUserRoleMapper.insert(sysUserRole);

                if (insert1 > 0) {
                    //新增菜单
                    List<SysRoleMenu> sysRoleMenus = sysRoleMenuMapper.selectById();

                    List<SysRoleMenu> collect = sysRoleMenus.stream().peek(item -> {
                        item.setTenantId(id);
                        item.setRoleId(roleId);
                    }).collect(Collectors.toList());

                    boolean b = sysRoleMenuMapper.insertBatch(collect);

                    if (b) {
                        //修改用户账套信息
                        sysUser.setTenantId(id);
                        sysUser.setAccountsId(id + "");
                        userMapper.updateById(sysUser);
                    }
                }
            }
        }
        return insertAccount;

    }

    /**
     * 根据ids获取名称(dubbo调用)
     */
    @Override
    public List<SysUser> getUserNameByIds(String userIds) {
        return userService.getUserNameByIds(userIds);
    }

    /**
     * 获取用户下拉
     */
    @Override
    public List<SysTheDropApiDto> userThe() {
        List<SysTheDropDto> sysTheDropDtos = userService.selectUserDropThe();
        List<SysTheDropApiDto> result = new ArrayList<>();
        for (SysTheDropDto entity : sysTheDropDtos) {
            SysTheDropApiDto sysTheDropApiDto = new SysTheDropApiDto();
            BeanUtils.copyProperties(entity, sysTheDropApiDto);
            result.add(sysTheDropApiDto);
        }
        return result;
    }

    /**
     * 构建登录用户
     */
    private LoginUser buildLoginUser(SysUser user) {
        LoginUser loginUser = new LoginUser();
        long userId = user.getUserId();
        String userName = user.getUserName();
        loginUser.setUserId(userId);
        loginUser.setDeptId(user.getDeptId());
        loginUser.setUsername(userName);
        loginUser.setPassword(user.getPassword());
        loginUser.setUserType(user.getUserType());
        loginUser.setMenuPermission(permissionService.getMenuPermission(user));
        loginUser.setRolePermission(permissionService.getRolePermission(user));
        loginUser.setDeptName(ObjectUtil.isNull(user.getDept()) ? "" : user.getDept().getDeptName());
        List<RoleDTO> roles = BeanUtil.copyToList(user.getRoles(), RoleDTO.class);
        loginUser.setRoles(roles);
        //租户id
        String accountsId = user.getAccountsId();
        if (StringUtils.isNotBlank(accountsId)) {
            RedisUtils.setCacheObject(String.valueOf(userId), accountsId);
        } else {
            RedisUtils.setCacheObject(String.valueOf(userId), userMapper.selectAccountsById(userName));
        }
        //查询物料辅助属性
        List<SysAuxiliary> listAuxiliary = userMapper.selectAuxiliary(accountsId);
        //缓存物料辅助属性
        Map<String, List<SysAuxiliary>> auxiliaryMap = StreamUtils.groupByKey(listAuxiliary, SysAuxiliary::getMaterialId);
        String ginseng = CacheNames.SYS_GINSENG + "_" + accountsId;
        auxiliaryMap.forEach((k, v) -> {
            CacheUtils.put(ginseng, k, v);
        });
        List<SysCustomDto> listCustom = sysFieldsMapper.selectCustom();
        //缓存自定义表头
        Map<String, List<SysCustomDto>> customMap = StreamUtils.groupByKey(listCustom, SysCustomDto::getTableName);
        String ginseng2 = CacheNames.SYS_CUSTOM + "_" + accountsId;
        customMap.forEach((k, v) -> {
            CacheUtils.put(ginseng2, k, v);
        });
        return loginUser;
    }

}
